]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
search: Use async functions instead of callbacks
authorFlorian Müllner <fmuellner@gnome.org>
Thu, 23 Jun 2022 16:13:36 +0000 (18:13 +0200)
committerMarge Bot <marge-bot@gnome.org>
Mon, 1 Aug 2022 18:51:14 +0000 (18:51 +0000)
Our search provider API has to be asynchronous to support remote
providers. It doesn't have to be based on callbacks though, now
that async functions provide a nicer alternative.

That is particularly true after gjs's D-Bus wrapper started to
generate promise-based method variants.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2344>

js/ui/appDisplay.js
js/ui/remoteSearch.js
js/ui/search.js

index cf76732e96b425601e4d203000afaf9b429e54bc..0768dee34dee61bdeb716694ccb7ea52bfebfaa6 100644 (file)
@@ -1825,7 +1825,7 @@ var AppSearchProvider = class AppSearchProvider {
         this._parentalControlsManager = ParentalControlsManager.getDefault();
     }
 
-    getResultMetas(apps, callback) {
+    getResultMetas(apps) {
         const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
         let metas = [];
         for (let id of apps) {
@@ -1852,24 +1852,25 @@ var AppSearchProvider = class AppSearchProvider {
             }
         }
 
-        callback(metas);
+        return new Promise(resolve => resolve(metas));
     }
 
     filterResults(results, maxNumber) {
         return results.slice(0, maxNumber);
     }
 
-    getInitialResultSet(terms, callback, _cancellable) {
+    getInitialResultSet(terms, cancellable) {
         // Defer until the parental controls manager is initialised, so the
         // results can be filtered correctly.
         if (!this._parentalControlsManager.initialized) {
-            let initializedId = this._parentalControlsManager.connect('app-filter-changed', () => {
-                if (this._parentalControlsManager.initialized) {
-                    this._parentalControlsManager.disconnect(initializedId);
-                    this.getInitialResultSet(terms, callback, _cancellable);
-                }
+            return new Promise(resolve => {
+                let initializedId = this._parentalControlsManager.connect('app-filter-changed', async () => {
+                    if (this._parentalControlsManager.initialized) {
+                        this._parentalControlsManager.disconnect(initializedId);
+                        resolve(await this.getInitialResultSet(terms, cancellable));
+                    }
+                });
             });
-            return;
         }
 
         let query = terms.join(' ');
@@ -1887,12 +1888,11 @@ var AppSearchProvider = class AppSearchProvider {
         });
 
         results = results.concat(this._systemActions.getMatchingActions(terms));
-
-        callback(results);
+        return new Promise(resolve => resolve(results));
     }
 
-    getSubsearchResultSet(previousResults, terms, callback, cancellable) {
-        this.getInitialResultSet(terms, callback, cancellable);
+    getSubsearchResultSet(previousResults, terms, cancellable) {
+        return this.getInitialResultSet(terms, cancellable);
     }
 
     createResultObject(resultMeta) {
index d9eef287f1aca68ddd3a56b7189b8a8425dfd249..0358b3404862b924fbe50a0f480cc048ecca5d34 100644 (file)
@@ -250,48 +250,43 @@ var RemoteSearchProvider = class {
         return regularResults.slice(0, maxNumber).concat(specialResults.slice(0, maxNumber));
     }
 
-    _getResultsFinished(results, error, callback) {
-        if (error) {
-            if (error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
-                return;
-
-            log(`Received error from D-Bus search provider ${this.id}: ${error}`);
-            callback([]);
-            return;
+    async getInitialResultSet(terms, cancellable) {
+        try {
+            const [results] = await this.proxy.GetInitialResultSetAsync(terms, cancellable);
+            return results;
+        } catch (error) {
+            if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
+                log(`Received error from D-Bus search provider ${this.id}: ${error}`);
+            return [];
         }
-
-        callback(results[0]);
-    }
-
-    getInitialResultSet(terms, callback, cancellable) {
-        this.proxy.GetInitialResultSetRemote(terms,
-                                             (results, error) => {
-                                                 this._getResultsFinished(results, error, callback);
-                                             },
-                                             cancellable);
     }
 
-    getSubsearchResultSet(previousResults, newTerms, callback, cancellable) {
-        this.proxy.GetSubsearchResultSetRemote(previousResults, newTerms,
-                                               (results, error) => {
-                                                   this._getResultsFinished(results, error, callback);
-                                               },
-                                               cancellable);
+    async getSubsearchResultSet(previousResults, newTerms, cancellable) {
+        try {
+            const [results] = await this.proxy.GetSubsearchResultSetAsync(previousResults, newTerms, cancellable);
+            return results;
+        } catch (error) {
+            if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
+                log(`Received error from D-Bus search provider ${this.id}: ${error}`);
+            return [];
+        }
     }
 
-    _getResultMetasFinished(results, error, callback) {
-        if (error) {
+    async getResultMetas(ids, cancellable) {
+        let metas;
+        try {
+            [metas] = await this.proxy.GetResultMetasAsync(ids, cancellable);
+        } catch (error) {
             if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
                 log(`Received error from D-Bus search provider ${this.id} during GetResultMetas: ${error}`);
-            callback([]);
-            return;
+            return [];
         }
-        let metas = results[0];
+
         let resultMetas = [];
         for (let i = 0; i < metas.length; i++) {
             for (let prop in metas[i]) {
                 // we can use the serialized icon variant directly
-                if (prop != 'icon')
+                if (prop !== 'icon')
                     metas[i][prop] = metas[i][prop].deep_unpack();
             }
 
@@ -303,15 +298,7 @@ var RemoteSearchProvider = class {
                 clipboardText: metas[i]['clipboardText'],
             });
         }
-        callback(resultMetas);
-    }
-
-    getResultMetas(ids, callback, cancellable) {
-        this.proxy.GetResultMetasRemote(ids,
-                                        (results, error) => {
-                                            this._getResultMetasFinished(results, error, callback);
-                                        },
-                                        cancellable);
+        return resultMetas;
     }
 
     activateResult(id) {
index 5375e7fc629b04a136550c6b9fbec28b0d2d9178..71870a039dc6dd900447e54709a4cd437710e755 100644 (file)
@@ -208,47 +208,40 @@ var SearchResultsBase = GObject.registerClass({
     _setMoreCount(_count) {
     }
 
-    _ensureResultActors(results, callback) {
+    async _ensureResultActors(results) {
         let metasNeeded = results.filter(
             resultId => this._resultDisplays[resultId] === undefined);
 
-        if (metasNeeded.length === 0) {
-            callback(true);
-        } else {
-            this._cancellable.cancel();
-            this._cancellable.reset();
-
-            this.provider.getResultMetas(metasNeeded, metas => {
-                if (this._cancellable.is_cancelled()) {
-                    if (metas.length > 0)
-                        log(`Search provider ${this.provider.id} returned results after the request was canceled`);
-                    callback(false);
-                    return;
-                }
-                if (metas.length != metasNeeded.length) {
-                    log(`Wrong number of result metas returned by search provider ${this.provider.id}: ` +
-                        `expected ${metasNeeded.length} but got ${metas.length}`);
-                    callback(false);
-                    return;
-                }
-                if (metas.some(meta => !meta.name || !meta.id)) {
-                    log(`Invalid result meta returned from search provider ${this.provider.id}`);
-                    callback(false);
-                    return;
-                }
-
-                metasNeeded.forEach((resultId, i) => {
-                    let meta = metas[i];
-                    let display = this._createResultDisplay(meta);
-                    display.connect('key-focus-in', this._keyFocusIn.bind(this));
-                    this._resultDisplays[resultId] = display;
-                });
-                callback(true);
-            }, this._cancellable);
+        if (metasNeeded.length === 0)
+            return;
+
+        this._cancellable.cancel();
+        this._cancellable.reset();
+
+        const metas = await this.provider.getResultMetas(metasNeeded, this._cancellable);
+
+        if (this._cancellable.is_cancelled()) {
+            if (metas.length > 0)
+                throw new Error(`Search provider ${this.provider.id} returned results after the request was canceled`);
         }
+
+        if (metas.length !== metasNeeded.length) {
+            throw new Error(`Wrong number of result metas returned by search provider ${this.provider.id}: ` +
+                `expected ${metasNeeded.length} but got ${metas.length}`);
+        }
+
+        if (metas.some(meta => !meta.name || !meta.id))
+            throw new Error(`Invalid result meta returned from search provider ${this.provider.id}`);
+
+        metasNeeded.forEach((resultId, i) => {
+            let meta = metas[i];
+            let display = this._createResultDisplay(meta);
+            display.connect('key-focus-in', this._keyFocusIn.bind(this));
+            this._resultDisplays[resultId] = display;
+        });
     }
 
-    updateSearch(providerResults, terms, callback) {
+    async updateSearch(providerResults, terms, callback) {
         this._terms = terms;
         if (providerResults.length == 0) {
             this._clearResultDisplay();
@@ -261,25 +254,23 @@ var SearchResultsBase = GObject.registerClass({
                 : providerResults;
             let moreCount = Math.max(providerResults.length - results.length, 0);
 
-            this._ensureResultActors(results, successful => {
-                if (!successful) {
-                    this._clearResultDisplay();
-                    callback();
-                    return;
-                }
+            try {
+                await this._ensureResultActors(results);
 
                 // To avoid CSS transitions causing flickering when
                 // the first search result stays the same, we hide the
                 // content while filling in the results.
                 this.hide();
                 this._clearResultDisplay();
-                results.forEach(resultId => {
-                    this._addItem(this._resultDisplays[resultId]);
-                });
+                results.forEach(
+                    resultId => this._addItem(this._resultDisplays[resultId]));
                 this._setMoreCount(this.provider.canLaunchSearch ? moreCount : 0);
                 this.show();
                 callback();
-            });
+            } catch (e) {
+                this._clearResultDisplay();
+                callback();
+            }
         }
     }
 });
@@ -638,11 +629,6 @@ var SearchResultsView = GObject.registerClass({
             provider.display.destroy();
     }
 
-    _gotResults(results, provider) {
-        this._results[provider.id] = results;
-        this._updateResults(provider, results);
-    }
-
     _clearSearchTimeout() {
         if (this._searchTimeoutId > 0) {
             GLib.source_remove(this._searchTimeoutId);
@@ -661,6 +647,25 @@ var SearchResultsView = GObject.registerClass({
         this._updateSearchProgress();
     }
 
+    async _doProviderSearch(provider, previousResults) {
+        provider.searchInProgress = true;
+
+        let results;
+        if (this._isSubSearch && previousResults) {
+            results = await provider.getSubsearchResultSet(
+                previousResults,
+                this._terms,
+                this._cancellable);
+        } else {
+            results = await provider.getInitialResultSet(
+                this._terms,
+                this._cancellable);
+        }
+
+        this._results[provider.id] = results;
+        this._updateResults(provider, results);
+    }
+
     _doSearch() {
         this._startingSearch = false;
 
@@ -668,23 +673,8 @@ var SearchResultsView = GObject.registerClass({
         this._results = {};
 
         this._providers.forEach(provider => {
-            provider.searchInProgress = true;
-
             let previousProviderResults = previousResults[provider.id];
-            if (this._isSubSearch && previousProviderResults) {
-                provider.getSubsearchResultSet(previousProviderResults,
-                                               this._terms,
-                                               results => {
-                                                   this._gotResults(results, provider);
-                                               },
-                                               this._cancellable);
-            } else {
-                provider.getInitialResultSet(this._terms,
-                                             results => {
-                                                 this._gotResults(results, provider);
-                                             },
-                                             this._cancellable);
-            }
+            this._doProviderSearch(provider, previousProviderResults);
         });
 
         this._updateSearchProgress();